package com.hello.system.controller;

import java.util.List;
import java.util.Date;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestHeader;
import com.hello.common.log.annotation.Log;
import com.hello.common.log.enums.BusinessType;
import com.hello.system.annotation.ContentSecurity;
import com.hello.system.domain.Letters;
import com.hello.system.service.ILettersService;
import com.hello.system.service.IEmailService;
import com.hello.system.utils.TaskExecutionLogger;
import com.hello.common.core.web.controller.BaseController;
import com.hello.common.core.web.domain.AjaxResult;
import com.hello.common.core.utils.poi.ExcelUtil;
import com.hello.common.core.web.page.TableDataInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 用户信件Controller
 * 
 * @author hello
 * @date 2025-05-15
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/letters")
public class LettersController extends BaseController
{
    private final ILettersService lettersService;
    
    private final TaskScheduler taskScheduler;
    
    private final IEmailService emailService;

    /**
     * 查询用户信件列表
     */
    @GetMapping("/list")
    public TableDataInfo list(Letters letters)
    {
        startPage();
        List<Letters> list = lettersService.selectLettersList(letters);
        return getDataTable(list);
    }

    /**
     * 导出用户信件列表
     */
    @Log(title = "用户信件", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Letters letters)
    {
        List<Letters> list = lettersService.selectLettersList(letters);
        ExcelUtil<Letters> util = new ExcelUtil<Letters>(Letters.class);
        util.exportExcel(response, list, "用户信件数据");
    }

    /**
     * 获取用户信件详细信息
     */
    @GetMapping(value = "/{letterId}")
    public AjaxResult getInfo(@PathVariable("letterId") Long letterId)
    {
        return success(lettersService.selectLettersByLetterId(letterId));
    }

    /**
     * 新增用户信件
     */
    @Log(title = "用户信件", businessType = BusinessType.INSERT)
    @PostMapping
    @ContentSecurity(fieldName = "content")
    public AjaxResult add(@RequestBody Letters letters, @RequestHeader(value = "X-WX-OPENID", required = false) String openid)
    {
        try {
            log.info("=== 开始创建用户信件，openid: {} ===", openid);
            log.info("信件创建请求参数: userId={}, title={}, letterMode={}, recipientEmail={}, sentAt={}", 
                     letters.getUserId(), letters.getTitle(), letters.getLetterMode(), 
                     letters.getRecipientEmail(), letters.getSentAt());
            
            // 内容安全检测由@ContentSecurity注解处理，但标题也需要检查
            if (letters.getTitle() != null && !letters.getTitle().isEmpty()) {
                // 将标题添加到内容前面，一起检测
                letters.setContent(letters.getTitle() + "\n" + letters.getContent());
            }
            
            // 检查是否有未来的发送时间
            Date sentAt = letters.getSentAt();
            Date now = new Date();
            boolean isScheduledForFuture = sentAt != null && sentAt.after(now);
            
            log.info("信件设置时间: {}, 当前时间: {}, 是否为未来发送: {}", 
                     sentAt, now, isScheduledForFuture);
            
            // 如果是电子信件且设置了未来发送时间，默认设置为draft状态
            if ("electronic".equals(letters.getLetterMode()) && isScheduledForFuture) {
                if (letters.getStatus() == null) {
                    letters.setStatus("draft");
                    log.info("电子信件设置为定时发送，状态设为: draft");
                }
            }
            
            log.info("开始持久化信件数据...");
            int rows = lettersService.insertLetters(letters);
            log.info("信件数据保存结果: 影响行数={}", rows);
            
            if (rows > 0) {
                // 如果是电子信件且设置了未来发送时间，创建定时任务
                if ("electronic".equals(letters.getLetterMode()) && isScheduledForFuture) {
                    log.info("检测到电子信件设置了未来发送时间，准备创建定时任务");
                    
                    // 获取包含ID的完整信件对象
                    Letters savedLetter = lettersService.selectLettersByLetterId(letters.getLetterId());
                    log.info("获取保存后的完整信件对象，信件ID: {}", savedLetter.getLetterId());
                    
                    if (savedLetter.getRecipientEmail() == null || savedLetter.getRecipientEmail().isEmpty()) {
                        log.warn("定时邮件缺少收件人邮箱地址，无法创建定时任务");
                        return error("定时邮件必须提供收件人邮箱地址");
                    }
                    
                    // 创建定时任务，在指定时间发送电子邮件
                    log.info("开始创建定时任务，计划发送时间: {}", savedLetter.getSentAt());
                    
                    // 使用TaskExecutionLogger记录任务创建
                    TaskExecutionLogger.logTaskStart(
                        "创建定时发送信件任务", 
                        "letterId", savedLetter.getLetterId(),
                        "title", savedLetter.getTitle(),
                        "recipientEmail", savedLetter.getRecipientEmail(),
                        "scheduledTime", savedLetter.getSentAt()
                    );
                    
                    taskScheduler.schedule(
                        () -> sendScheduledEmail(savedLetter),
                        savedLetter.getSentAt()
                    );
                    
                    log.info("定时任务创建成功，信件ID: {}, 将在 {} 发送到 {}", 
                             savedLetter.getLetterId(), 
                             savedLetter.getSentAt(),
                             savedLetter.getRecipientEmail());
                             
                    TaskExecutionLogger.logTaskSuccess(
                        "创建定时发送信件任务", 
                        String.format("成功为信件ID %d 创建定时发送任务，将在 %s 发送到 %s", 
                            savedLetter.getLetterId(), 
                            savedLetter.getSentAt(), 
                            savedLetter.getRecipientEmail())
                    );
                } else {
                    log.info("非定时电子信件或未设置未来发送时间，不创建定时任务");
                }
                
                Letters resultLetter = lettersService.selectLettersByLetterId(letters.getLetterId());
                log.info("=== 信件创建完成，ID: {} ===", resultLetter.getLetterId());
                return success(resultLetter);
            }
            log.error("信件创建失败，数据库操作未返回有效结果");
            return error("新增信件失败");
        } catch (Exception e) {
            log.error("新增信件失败，异常详情: ", e);
            String errorMsg = e.getMessage();
            if (errorMsg != null) {
                if (errorMsg.contains("sd_letters_ibfk_1") && errorMsg.contains("user_id")) {
                    log.error("外键约束错误：用户ID不存在 (userId: {})", letters.getUserId());
                    return error("用户ID不存在，请确认提供的userId是否正确");
                } else if (errorMsg.contains("sd_letters_ibfk_2") && errorMsg.contains("stationery_template_id")) {
                    log.error("外键约束错误：信笺模板ID不存在 (templateId: {})", letters.getStationeryTemplateId());
                    return error("信笺模板ID不存在，请确认提供的stationeryTemplateId是否正确");
                }
            }
            
            // 记录创建信件任务失败
            TaskExecutionLogger.logTaskFailure(
                "创建信件任务", 
                "创建信件失败: " + errorMsg, 
                e
            );
            
            return error("新增信件失败: " + errorMsg);
        }
    }
    
    /**
     * 发送定时电子邮件
     */
    private void sendScheduledEmail(Letters letter) {
        try {
            // 使用TaskExecutionLogger记录任务开始
            TaskExecutionLogger.logTaskStart(
                "定时发送信件邮件", 
                "letterId", letter.getLetterId(),
                "title", letter.getTitle(),
                "recipientEmail", letter.getRecipientEmail(),
                "sentAt", letter.getSentAt()
            );
            
            log.info("=== 开始执行定时发送邮件任务 ===");
            log.info("信件ID: {}, 收件人: {}, 标题: {}", 
                     letter.getLetterId(), letter.getRecipientEmail(), letter.getTitle());
            
            // 验证邮件必要信息
            if (letter.getRecipientEmail() == null || letter.getRecipientEmail().isEmpty()) {
                String errorMsg = "定时邮件缺少收件人邮箱地址，无法发送";
                log.error(errorMsg + "，信件ID: {}", letter.getLetterId());
                TaskExecutionLogger.logTaskFailure("定时发送信件邮件", errorMsg, null);
                return;
            }
            
            log.info("开始发送电子邮件...");
            // 发送电子邮件
            emailService.sendEmail(
                letter.getRecipientEmail(),
                letter.getTitle(),
                letter.getContent()
            );
            
            log.info("电子邮件发送成功，开始更新信件状态");
            // 更新信件状态为已发送
            letter.setStatus("sent");
            // 确保sentAt字段已设置(虽然之前应该已经设置了)
            if (letter.getSentAt() == null) {
                letter.setSentAt(new Date());
                log.info("设置信件发送时间为当前时间: {}", letter.getSentAt());
            }
            
            int result = lettersService.updateLetters(letter);
            log.info("信件状态更新结果: 影响行数={}", result);
            
            log.info("=== 定时信件发送任务执行完成，信件ID: {} ===", letter.getLetterId());
            
            // 使用TaskExecutionLogger记录任务成功完成
            TaskExecutionLogger.logTaskSuccess(
                "定时发送信件邮件", 
                String.format("成功发送信件ID %d 的电子邮件到 %s，标题: %s", 
                    letter.getLetterId(), 
                    letter.getRecipientEmail(), 
                    letter.getTitle())
            );
            
        } catch (Exception e) {
            log.error("定时发送信件失败，信件ID: {}, 异常详情: ", letter.getLetterId(), e);
            
            // 使用TaskExecutionLogger记录任务失败
            TaskExecutionLogger.logTaskFailure(
                "定时发送信件邮件", 
                String.format("发送信件ID %d 的电子邮件到 %s 失败: %s", 
                    letter.getLetterId(), 
                    letter.getRecipientEmail(), 
                    e.getMessage()),
                e
            );
        }
    }

    /**
     * 修改用户信件
     */
    @Log(title = "用户信件", businessType = BusinessType.UPDATE)
    @PutMapping
    @ContentSecurity(fieldName = "content")
    public AjaxResult edit(@RequestBody Letters letters, @RequestHeader(value = "X-WX-OPENID", required = false) String openid)
    {
        // 内容安全检测由@ContentSecurity注解处理，通过请求头获取openid
        log.info("修改用户信件，openid: {}", openid);
        
        // 标题也需要检测内容安全
        if (letters.getTitle() != null && !letters.getTitle().isEmpty() && letters.getContent() != null) {
            letters.setContent(letters.getTitle() + "\n" + letters.getContent());
        }
        
        return toAjax(lettersService.updateLetters(letters));
    }

    /**
     * 删除用户信件
     */
    @Log(title = "用户信件", businessType = BusinessType.DELETE)
	@DeleteMapping("/{letterIds}")
    public AjaxResult remove(@PathVariable Long[] letterIds)
    {
        return toAjax(lettersService.deleteLettersByLetterIds(letterIds));
    }
}
